package junit;

import java.io.FileNotFoundException;
import java.io.IOException;

import org.junit.*;

import fast.*;
import static org.junit.Assert.*;

public class MasterProcessorTest {

	private MasterProcessor mp;

	private Buffer sendBuffer;
	private Thread sender;

	private Buffer listenBuffer;
	private Thread listener;

	private Buffer udpListenBuffer;
	private Thread udpListener;

	public static void main(String[] args) throws Exception {
		MasterProcessorTest mpt = new MasterProcessorTest();

		mpt.load_state();

		mpt.test_login();
		mpt.test_logout();

		// can be tested directly
		mpt.test_validateFile();
		mpt.test_splitFile();
		mpt.test_running();

		// test via packet sends
		mpt.test_join();
		mpt.test_leave();
		mpt.test_complete();
		mpt.test_done();

		mpt.unload_state();
	}

	private void test_running() {
		System.out.println("Test: test_running 1 of 1");
		System.out.println("******************");
		
		assertTrue(mp.getRunning());
		
		System.out.println("test passed.\n\n");
	}


	private void test_splitFile() throws InterruptedException {
		System.out.println("Test: test_splitfile 1 of 1");
		System.out.println("******************");
		
		// add localhost as a slave
		sendBuffer.add("localhost", 5000, 1, CommandsEnum.SYSTEM_JOIN
				.toString(), "10000");
		
		Thread.sleep(2000);
		listenBuffer.remove();

		mp.splitFile("testimage.iso");

		Thread.sleep(2000);
		
		assertTrue(listenBuffer.remove().equals("127.0.0.1|1|LOAD|testimage.iso,0,20"));
	
		System.out.println("test passed.\n\n");
	}

	private void test_validateFile() {
		System.out.println("Test: test_validatefile 1 of 2");
		System.out.println("******************");
		assertTrue(mp.validateFile("testimage.iso"));
		System.out.println("test passed.\n\n");
		
		System.out.println("Test: test_validatefile 2 of 2");
		System.out.println("******************");
		assertFalse(mp.validateFile("test.jpg"));
		System.out.println("test passed.\n\n");
	}

	private void test_logout() {
		// assumes that test_login() is called first.
		System.out.println("Test: test_logout 1 of 1");
		System.out.println("******************");
		mp.logout();

		assertTrue(mp.getUserID() == null);
		System.out.println("test passed.\n\n");

	}

	private void test_login() {
		// assumes no previous logins.		
		System.out.println("Test: test_login 1 of 2");
		System.out.println("******************");
		
		assertTrue(mp.getUserID() == null);
		System.out.println("test passed.\n\n");

		System.out.println("Test: test_login 2 of 2");
		System.out.println("******************");
		mp.login("testuser");

		assertTrue(mp.getUserID().equals("testuser"));
		System.out.println("test passed.\n\n");
	}

	public void test_join() throws InterruptedException {
		System.out.println("Test: test_join 1 of 2");
		System.out.println("******************");
		
		// send a 'JOIN' command
		sendBuffer.add("localhost", 5000, 1, CommandsEnum.SYSTEM_JOIN
				.toString(), "10000");

		Thread.sleep(2000);

		// print the received 'DONE' command
		assertTrue(listenBuffer.remove().equals("127.0.0.1|1|DONE|null"));
		System.out.println("test passed.\n\n");

		System.out.println("Test: test_join 2 of 2");
		System.out.println("******************");
		// check that the new host is in the peermanager
		assertTrue(mp.peerMgr.contains("127.0.0.1"));
		System.out.println("test passed.\n\n");

	}

	public void test_leave() throws InterruptedException {

		
		// send a 'LEAVE' command
		sendBuffer.add("localhost", 5000, 1, CommandsEnum.SYSTEM_LEAVE
				.toString(), "");

		Thread.sleep(2000);

		System.out.println("Test: test_leave 1 of 3");
		System.out.println("******************");
		assertTrue(listenBuffer.remove().equals("127.0.0.1|2|DONE|"));
		System.out.println("test passed.\n\n");

		// check that there are no entries for the host in the statemanager
		System.out.println("Test: test_leave 2 of 3");
		System.out.println("******************");
		assertFalse(mp.stateMgr.contains("127.0.0.1"));
		System.out.println("test passed.\n\n");

		// check that the new host is NOT in the peermanager
		System.out.println("Test: test_leave 3 of 3");
		System.out.println("******************");
		assertFalse(mp.peerMgr.contains("127.0.0.1"));
		System.out.println("test passed.\n\n");
	}

	private void test_complete() throws InterruptedException {
		// send a 'JOIN' command
		sendBuffer.add("localhost", 5000, 1, CommandsEnum.SYSTEM_JOIN
				.toString(), "10000");

		Thread.sleep(2000);
		
		//send a 'SEARCH' command
		mp.sendSearch("foo");
		
		Thread.sleep(2000);
		
		System.out.println("Test: test_complete 1 of 2");
		System.out.println("******************");
		//check host is in the statemgr
		assertTrue(mp.stateMgr.contains("127.0.0.1"));
		System.out.println("test passed.\n\n");
		
		//send a 'COMPLETE' command
		sendBuffer.add("localhost", 5000, 3, CommandsEnum.SYSTEM_COMPLETE.toString(),"");

		Thread.sleep(2000);
		
		System.out.println("Test: test_complete 2 of 2");
		System.out.println("******************");
		//verify that the host is no longer in the statemanager
		assertFalse(mp.stateMgr.contains("127.0.0.1"));
		System.out.println("test passed.\n\n");
	
	}

	private void test_done() throws InterruptedException {
		// send a 'JOIN' command
		sendBuffer.add("localhost", 5000, 1, CommandsEnum.SYSTEM_JOIN
				.toString(), "10000");

		Thread.sleep(2000);
		
		//send a 'SEARCH' command
		mp.sendSearch("foo");
		
		Thread.sleep(2000);
		
		System.out.println("Test: test_done 1 of 2");
		System.out.println("******************");
		//check host is in the statemgr
		assertTrue(mp.stateMgr.contains("127.0.0.1"));
		System.out.println("test passed.\n\n");
		
		//send a 'COMPLETE' command
		sendBuffer.add("localhost", 5000, 4, CommandsEnum.SYSTEM_DONE.toString(),"");

		Thread.sleep(2000);
		
		System.out.println("Test: test_done 2 of 2");
		System.out.println("******************");
		//verify that the host is no longer in the statemanager
		assertFalse(mp.stateMgr.contains("127.0.0.1"));
		System.out.println("test passed.\n\n");

	}

	public void load_state() throws FileNotFoundException, IOException {
		mp = MasterProcessor.getMasterProcessor();
		sendBuffer = new Buffer(10);
		sender = new Thread(new TCPTalker(sendBuffer));
		listenBuffer = new Buffer(10);
		listener = new Thread(new TCPListener(10000, listenBuffer));

		udpListenBuffer = new Buffer(10);
		udpListener = new Thread(new UDPListener(6000, udpListenBuffer));

		udpListener.start();
		listener.start();
		sender.start();
		mp.start();
	}

	public void unload_state() {
		udpListener = null;
		listener = null;
		sender = null;

		mp.quit();

		mp = null;
		
		System.exit(0);

	}

}
